#include <string.h>
#include <errno.h>
#include "epoll_event.h"
#include "http_server.h"
#include "log.h"

int epoll_create_event_manager (int size)
{
	int fd;

	if ((fd = epoll_create (size)) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_create: %s.", strerror (errno));
		}

		return -1;
	}

	return fd;
}

int epoll_add_fd (int fd, int events)
{
	struct epoll_event ev;

	ev.events = events;
	ev.data.u64 = 0;
	ev.data.fd = fd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_ADD, fd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int epoll_del_fd (http_connection_t *http_connection)
{
	struct epoll_event ev;

	ev.events = 0;
	ev.data.u64 = 0;
	ev.data.fd = http_connection->sd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_DEL, http_connection->sd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int epoll_del_listener (int fd)
{
	struct epoll_event ev;

	ev.events = 0;
	ev.data.u64 = 0;
	ev.data.fd = fd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_DEL, fd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int epoll_event_wait (int timeout)
{
	return epoll_wait (http_server.event_manager, http_server.events, http_server.max_file_descriptors, timeout);
}

int epoll_prepare_for_reading (http_connection_t *http_connection)
{
	struct epoll_event ev;

	/* Notify me of readable events. */
	ev.events = EPOLLIN;
	ev.data.u64 = 0;
	ev.data.fd = http_connection->sd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_MOD, http_connection->sd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int epoll_prepare_for_writing (http_connection_t *http_connection)
{
	struct epoll_event ev;

	/* Notify me of writeable events. */
	ev.events = EPOLLOUT;
	ev.data.u64 = 0;
	ev.data.fd = http_connection->sd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_MOD, http_connection->sd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}

int epoll_remove_notifications (http_connection_t *http_connection)
{
	struct epoll_event ev;

	ev.events = 0;
	ev.data.u64 = 0;
	ev.data.fd = http_connection->sd;

	if (epoll_ctl (http_server.event_manager, EPOLL_CTL_MOD, http_connection->sd, &ev) < 0) {
		if (http_server.log_fd != -1) {
			log_error ("epoll_ctl: %s.", strerror (errno));
		}

		return -1;
	}

	return 0;
}
